package ru.ifmo.rybakov.muclumon.pes;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.ifmo.rybakov.muclumon.Database;
import ru.ifmo.rybakov.muclumon.Properties;
import ru.ifmo.rybakov.muclumon.PropertyValueFactory;
import ru.ifmo.rybakov.muclumon.Revision;
import ru.ifmo.rybakov.muclumon.RevisionFactory;
import ru.ifmo.rybakov.muclumon.RevisionType;
import ru.ifmo.rybakov.muclumon.Task;
import ru.ifmo.rybakov.muclumon.pes.sr.SequenceRunType;
import ru.ifmo.rybakov.muclumon.pes.sri.SequenceRunInfo;

public class SequenceStartedEventHandler implements IEventHandler {

	private static final Logger logger = LoggerFactory.getLogger(SequenceStartedEventHandler.class);
	
	/* (non-Javadoc)
	 * @see ru.ifmo.rybakov.muclumon.pes.IEventHandler#handle(ru.ifmo.rybakov.muclumon.pes.sri.SequenceRunInfo, ru.ifmo.rybakov.muclumon.pes.sr.SequenceRunType)
	 */
	@Override
	public void handle(SequenceRunInfo sequenceRunInfo, SequenceRunType sequenceRun) {
		
		// check consistency
//		if (!sequenceRunInfo.getId().equals(sequenceRun.getId())) {
//			logger.error("Sequence run info id ({}) and sequence run id ({}) are not equal",
//					new Object[] { sequenceRunInfo.getId(), sequenceRun.getId() });
//			return;
//		}
		
		logger.debug("Processing sequence start, id={}", sequenceRunInfo.getId());
		
		// process sequence run
		List<SequenceRunType.Step> steps = sequenceRun.getStep();
		if (steps == null || steps.size() == 0) {
			logger.error("No steps provided in sequence run, can not process event");
			return;
		}
		SequenceRunType.Step sequenceRunStep = steps.get(0);
		
		// create task entity and set appropriate properties
		Task task = new Task();
		task.setForeignId(sequenceRun.getId().intValue()); // bind to task id
		task.addPropertyValue(PropertyValueFactory.createDateTimeValue(Properties.SEQUENCE_STARTED, new DateTime(sequenceRunInfo.getTime().getStamp().toGregorianCalendar())));
		
		// parameter: application
		String appName = sequenceRunStep.getApp().getName();
		task.addPropertyValue(PropertyValueFactory.createStringValue(Properties.TASK_APPLICATION, appName));
		
		// parameter: method
		String methodName = sequenceRunStep.getMethod().getName();
		if (!"".equals(methodName)) {
			task.addPropertyValue(PropertyValueFactory.createStringValue(Properties.TASK_METHOD, methodName));
		} // set only if not empty
		
		// custom parameters
		List<SequenceRunType.Step.Param> parameters = sequenceRunStep.getParam();
		if (parameters != null) {
			for (SequenceRunType.Step.Param p : parameters) {
				task.addPropertyValue(PropertyValueFactory.create(p.getName(), p.getValue()));
			}
		}
		
		// persist in database
		Revision revision = RevisionFactory.createRevision(RevisionType.TASK_CONFIGURATION);
		task.setRevision(revision);
		
		EntityManager em = Database.getEntityManagerFactory().createEntityManager();
		try {
			EntityTransaction t = em.getTransaction();
			try {
				t.begin();
				em.persist(task);
				t.commit();
			} finally {
				if (t.isActive()) t.rollback();
			}
		} finally {
			em.close();
		}
		
		logger.debug("Sequence started, task info persisted, waiting for step to be started");
	}
	
}
